﻿using Entity.BaseEntitys;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions;
using ShardingCore.Sharding;
using ShardingCore.Sharding.Abstractions;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
namespace EntityFrameWorkCore
{

    public abstract  class BaseDbContext<IDbContext> : AbstractShardingDbContext, IShardingTableDbContext where IDbContext : DbContext
    {
       


        public BaseDbContext(DbContextOptions<IDbContext> options) : base(options)
        {
 
        }


        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {

            var types = modelBuilder.Model.GetEntityTypes();
            var delType = typeof(IDeleteEntity);
            foreach (var entityType in types)
            {
                var type = entityType.ClrType;
                var entityTypeBuilder = modelBuilder.Entity(type);
                var id = entityTypeBuilder.Property("Id");
                if (id.Metadata.ClrType.Name == "Guid")
                    id.HasValueGenerator<SequentialGuidValueGenerator>();

                if (delType.IsAssignableFrom(type))
                {
                    var parameter = Expression.Parameter(type);
                    var propertyMethodInfo = typeof(EF).GetMethod(nameof(EF.Property)).MakeGenericMethod(typeof(bool));
                    var isDeletedProperty = Expression.Call(propertyMethodInfo, parameter, Expression.Constant(nameof(IDeleteEntity.IsDeleted)));
                    var compareExpression = Expression.MakeBinary(ExpressionType.Equal, isDeletedProperty, Expression.Constant(false));
                    var lambda = Expression.Lambda(compareExpression, parameter);
                    entityTypeBuilder.HasQueryFilter(lambda);
                }
                
            }


            base.OnModelCreating(modelBuilder);

        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
            => optionsBuilder.LogTo(message => Debug.WriteLine(message));




        #region  事务
        /// <summary>
        /// 开启事务
        /// </summary>
        /// <returns></returns>
        public virtual IDbContextTransaction BeginTransaction() => base.Database.BeginTransaction();

        /// <summary>
        /// 开启事务
        /// </summary>
        /// <returns></returns>
        public virtual Task<IDbContextTransaction> BeginTransactionAsync() => base.Database.BeginTransactionAsync();


        /// <summary>
        /// 提交事务
        /// </summary>
        /// <returns></returns>
        public virtual void CommitTransaction() => base.Database.CommitTransaction();

        /// <summary>
        /// 提交事务
        /// </summary>
        /// <returns></returns>
        public virtual Task CommitTransactionAsync => base.Database.CommitTransactionAsync();


        /// <summary>
        /// 回滚事务
        /// </summary>
        /// <returns></returns>
        public virtual void RollbackTransaction() => base.Database.RollbackTransaction();

        /// <summary>
        /// 回滚事务
        /// </summary>
        /// <returns></returns>
        public virtual Task RollbackTransactionAsync => base.Database.RollbackTransactionAsync();

        public IRouteTail RouteTail { get; set; }
        #endregion



    }
}
